package earogya.ehr.patient_details.messages;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.DataTypeException;
import ca.uhn.hl7v2.model.v251.datatype.XAD;
import ca.uhn.hl7v2.model.v251.datatype.XPN;
import ca.uhn.hl7v2.model.v251.message.ADT_A01;
import ca.uhn.hl7v2.model.v251.segment.PD1;
import ca.uhn.hl7v2.model.v251.segment.PID;
import earogya.ehr.patient_details.HibernateManager;
import earogya.ehr.patient_details.Patient;
import earogya.ehr.patient_details.PatientAddress;
import earogya.ehr.patient_details.PatientEmail;
import earogya.ehr.patient_details.PatientTelephone;

/***
 * 
 * @author Ureka
 * 
 * This message is used to update the demographic details of a patient already registered
 * in the system.
 * 
 */
public class ADT_A08_Handler {
	private Patient patient = new Patient();
	private PatientAddress pAddress;
	private PatientEmail pEmail;
	private PatientTelephone pTelephone;
	private List<PatientTelephone> patientTelephoneUpdateList = new ArrayList<PatientTelephone>();
	private List<PatientEmail> patientEmailUpdateList = new ArrayList<PatientEmail>();
	private List<Object> patientTelephoneCreateList = new ArrayList<Object>();
	private List<Object> patientEmailCreateList = new ArrayList<Object>();
	HibernateManager hibernateManager = new HibernateManager();

	private ADT_A01 adtMsg;

	public ADT_A08_Handler(ADT_A01 adtMsg) {
		this.adtMsg = adtMsg;
	}

	
	/**
	 * Update the patient details based on the message fields.
	 * 
	 * @return
	 * @throws HibernateException
	 * @throws HL7Exception
	 * @throws IOException
	 */
	public String manageMessage() throws HibernateException, HL7Exception,IOException {
		String ack = null;
		try {
			Boolean isUpdateSuccess = this.updatePatientDetails();
			Boolean isAddressUpdateSuccess = this.updatePatientAddressDetails();
			updatePatientEmailAndTelephoneDetails();
			if (isUpdateSuccess && isAddressUpdateSuccess) {
				ack = adtMsg.generateACK().encode();
			}

		} catch (HibernateException e) {
			HL7Exception ex = new HL7Exception("Could not save to Database");
			ack = adtMsg.generateACK("AE", ex).encode();
		} catch (IOException e) {
			HL7Exception ex = new HL7Exception("An IO error ocuured");
			ack = adtMsg.generateACK("AE", ex).encode();
		} catch (DataTypeException e) {
			HL7Exception ex = new HL7Exception(
					"An error occured while data type conversion");
			ack = adtMsg.generateACK("AE", ex).encode();
		} catch (HL7Exception e) {
			HL7Exception ex = new HL7Exception("Could not parse the message");
			ack = adtMsg.generateACK("AE", ex).encode();
		} catch (Exception e) {
			HL7Exception ex = new HL7Exception("An error occured");
			ack = adtMsg.generateACK("AE", ex).encode();
		}
		return ack;
	}

	
	/**
	 * 
	 * Update patient details
	 * 
	 * @return
	 * @throws HL7Exception
	 * @throws IOException
	 * @throws HibernateException
	 * @throws DataTypeException
	 */
	public Boolean updatePatientDetails() throws HL7Exception, IOException,HibernateException, DataTypeException {
		Boolean isSucess = false;
		try {
			PID pid = adtMsg.getPID();
			PD1 pd1 = adtMsg.getPD1();
			patient.setPatientId(Integer.parseInt(pid.getPatientID().getIDNumber().getValue()));
			XPN pName = pid.getPatientName(0);
			if (pName.getPrefixEgDR().getValue() == null) {
			} else {
				patient.setPrefix(pName.getPrefixEgDR().getValue());
			}
			if (pName.getGivenName().getValue() == null) {
			} else {
				patient.setGivenName(pName.getGivenName().getValue());
			}
			if (pName.getFamilyName().getSurname().getValue() == null) {
			} else {
				patient.setFamilyName(pName.getFamilyName().getSurname()
						.getValue());
			}
			if (pid.getPatientIdentifierList(0).getIDNumber().getValue() == null) {
			} else {
				patient.setNicNo(pid.getPatientIdentifierList(0).getIDNumber()
						.getValue());
			}
			if (pid.getAdministrativeSex().getValue() == null) {
			} else {
				patient.setGender(pid.getAdministrativeSex().getValue());
			}
			if (pid.getDateTimeOfBirth().getTime().getValue() == null) {
			} else {
				patient.setBirthTime(pid.getDateTimeOfBirth().getTime()
						.getValueAsDate());
			}
			if (pid.getBirthPlace().getValue() == null) {
			} else {
				patient.setBirthPlaceAddress(pid.getBirthPlace().toString());
			}
			if (pid.getMultipleBirthIndicator().getValue() == null) {
			} else {
				patient.setMultipleBirthIndex(Short.valueOf(pid
						.getMultipleBirthIndicator().getValue()));
			}
			if (pid.getBirthOrder() == null) {
				patient.setMultipleBirthOrderNumber(Short.valueOf(pid
						.getBirthOrder().getValue()));
			}
			if (pd1.getOrganDonorCode().getValue() == null) {
			} else {
				patient.setOrganDonorIndex(Integer.valueOf(pd1
						.getOrganDonorCode().getValue()));
			}
			if (pid.getMaritalStatus().getComponent(0).toString() == null) {
			} else {
				patient.setMaritialStatus(pid.getMaritalStatus()
						.getComponent(0).toString());
			}
			if (pd1.getLivingArrangement().getValue() == null) {
			} else {
				patient.setLivingArrangementId(Integer.valueOf(pd1
						.getLivingArrangement().getValue()));
			}
			if (pid.getReligion().getComponent(0).toString() == null) {
			} else {
				patient.setReligiousAffliationId(pid.getReligion()
						.getComponent(0).toString());
			}
			if (pid.getEthnicGroup(0).getComponent(0).toString() == null) {
			} else {
				patient.setEthnicGroupId(pid.getEthnicGroup(0).getComponent(0)
						.toString());
			}
			if (pid.getPatientDeathIndicator().getValue() == null) {
			} else {
				patient.setDeceasedIndex(Boolean.parseBoolean(pid
						.getPatientDeathIndicator().getValue()));
			}
			if (pid.getPatientDeathDateAndTime().getTime().getValue() == null) {
			} else {
				patient.setDeceasedTime(pid.getPatientDeathDateAndTime()
						.getTime().getValueAsDate());
			}
			hibernateManager.update(patient);
			isSucess = true;
		} catch (Exception e) {
			isSucess = false;
		}
		return isSucess;
	}

	
	/**
	 * 
	 * Update patient's address details
	 * 
	 * @return
	 * @throws HL7Exception
	 * @throws IOException
	 * @throws HibernateException
	 * @throws DataTypeException
	 */
	public Boolean updatePatientAddressDetails() throws HL7Exception,
			IOException, HibernateException, DataTypeException {
		Boolean isSuccess = false;
		PID pid = adtMsg.getPID();
		XAD[] addressList = pid.getPatientAddress();
		try {
			for (int i = 0; i < addressList.length; i++) {
				pAddress = new PatientAddress();
				pAddress.setPatientId(this.patient.getPatientId());
				pAddress.setCity1(addressList[i].getOtherDesignation()
						.getValue());
				pAddress.setCountry(addressList[i].getCountry().getValue());
				pAddress.setHouseNumber(addressList[i].getStreetAddress()
						.getDwellingNumber().getValue());
				pAddress.setCity2(addressList[i].getCity().getValue());
				pAddress.setStreet(addressList[i].getStreetAddress()
						.getStreetName().getValue());
				hibernateManager.saveObject(pAddress);
				isSuccess = true;
			}
		} catch (HibernateException e) {
			isSuccess = false;
		}
		return isSuccess;
	}

	
	/**
	 * 
	 * Update patient's email and telephone details
	 * 
	 * @throws HL7Exception
	 * @throws IOException
	 * @throws HibernateException
	 * @throws DataTypeException
	 */
	public void updatePatientEmailAndTelephoneDetails() throws HL7Exception,IOException, HibernateException, DataTypeException {
		Object[][] fieldsAndValues = { { "patientId", patient.getPatientId() } };
		String[] requiredFields = {};
		List patientTelephoneNumberIds = hibernateManager.queryValueListFromDatabase(fieldsAndValues,
						"patientTelephoneNoId", "PatientTelephone","patientTelephone");
		List patientEmailIds = hibernateManager.queryValueListFromDatabase(fieldsAndValues, 
				"patientEmailId", "PatientEmail","patientEmail");
		PID pid = adtMsg.getPID();
		int i = 0;
		while (!(pid.getPhoneNumberHome(i).getTelephoneNumber().getValue() == null)
				|| !(pid.getPhoneNumberHome(i).getEmailAddress().getValue() == null)) {

			if (pid.getPhoneNumberHome(i).getTelephoneNumber().getValue() == null) {
			} else {
				pTelephone = new PatientTelephone();
				pTelephone.setPatientId(this.patient.getPatientId());
				pTelephone.setTelephoneNo(pid.getPhoneNumberHome(i).getTelephoneNumber().getValue());
				if (i < patientTelephoneNumberIds.size()) {
					pTelephone.setPatientTelephoneNoId(Integer.parseInt(patientTelephoneNumberIds.get(i).toString()));
					patientTelephoneUpdateList.add(pTelephone);
				} else {
					patientTelephoneCreateList.add(pTelephone);
				}
			}

			if (pid.getPhoneNumberHome(i).getEmailAddress().getValue() == null) {
			} else {
				pEmail = new PatientEmail();
				pEmail.setPatientId(this.patient.getPatientId());
				pEmail.setEmail(pid.getPhoneNumberHome(i).getEmailAddress().getValue());
				if (i < patientEmailIds.size()) {
					pEmail.setPatientEmailId(Integer.parseInt(patientEmailIds.get(i).toString()));
					patientEmailUpdateList.add(pEmail);
				} else {
					patientEmailCreateList.add(pEmail);
				}
			}
			i++;
		}
		hibernateManager.updateTelephoneList(patientTelephoneUpdateList);
		hibernateManager.updateEmailList(patientEmailUpdateList);
		hibernateManager.saveObjectList(patientTelephoneCreateList);
		hibernateManager.saveObjectList(patientEmailCreateList);
	}

}
